
package uk.ac.cam.cl.oscar.edgefinder;

import java.awt.Point;
import java.lang.Math;

/** Two spaces exist, normalised space (everything lies within a unit circle)
    and plain old screen space. This class makes conversion simple. */
public class NormalisedPoint {

	private double x;
	private double y;

	public NormalisedPoint () {
		x = 0;
		y = 0;
	}
	
	public NormalisedPoint (NormalisedPoint p) {
		x = p.x;
		y = p.y;
	}
	
	/* Create with normalised coordinates */
	public NormalisedPoint (double x, double y) {
		this.x = x;
		this.y = y;
	}

	/* Create with normalised coordinates */
	public NormalisedPoint (float x, float y) {
		this.x = x;
		this.y = y;
	}
	
	public void setNormalX (double x) { this.x = x; }
	public void setNormalY (double y) { this.y = y; }
	
	public void initFromScreen (int x, int y, int width, int height) {
		double sf = toNormalSF (width, height);
		this.x = (double)(x - width / 2) * sf;
		this.y = (double)(y - height / 2)* sf;
	}
	
	static public double toNormalSF (int width, int height) {
		double ratioAngle = Math.atan ((double)height / (double)width);
		return Math.sin(ratioAngle) / (double)height;
	}
	
	static public double toScreenSF (int width, int height) {
		return 1.0 / toNormalSF (width, height);
	}
	
	public int screenX (int width, int height) { return width/2+(int)Math.round(x * toScreenSF(width, height)); }
	public int screenY (int width, int height) { return height/2+(int)Math.round(y * toScreenSF(width, height)); }
	
	/** Normal X */
	public double x () { return x; }
	
	/** Normal Y */
	public double y () { return y; }
	
	public double normalX () { return x; }
	public double normalY () { return y; }
	
        public boolean equals(NormalisedPoint other) { return ((this.x == other.x()) && (this.y == other.y())); }

	public static double normalDistance (NormalisedPoint a, NormalisedPoint b) 
	{
		return Math.sqrt((b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y));
	}
	
	public Point screenPoint (int width, int height) {
		Point p = new Point();
		double sf = toScreenSF (width, height);
		p.x = (int)(x * sf);
		p.y = (int)(y * sf);
		return p;
	}
	

}
